package com.adnaan.backend.service.impl;

import com.adnaan.backend.entity.SysPermission;
import com.adnaan.backend.entity.dto.PermissionTree;
import com.adnaan.backend.entity.vo.RoleAuthority;
import com.adnaan.backend.mapper.SysPermissionMapper;
import com.adnaan.backend.service.SysPermissionService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 系统权限服务实现类
 *
 * @author adnaan
 * @since 2025-01-12
 */
@Service
public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission> implements SysPermissionService {

    /**
     * 构建树形结构
     * 该方法会递归查询每个节点的子节点，并构建完整的树形结构
     *
     * @param records 需要构建树形结构的权限记录列表
     */
    @Override
    public void tree(List<SysPermission> records) {
        // 参数校验
        if (CollectionUtils.isEmpty(records)) {
            return;
        }

        // 获取所有记录的ID集合，用于批量查询子节点
        Set<Long> parentIds = records.stream()
                .map(SysPermission::getId)
                .collect(Collectors.toSet());

        // 一次性查询所有可能的子节点，减少数据库查询次数
        LambdaQueryWrapper<SysPermission> childrenQuery = new LambdaQueryWrapper<>();
        childrenQuery.in(SysPermission::getParentId, parentIds)
                .orderByAsc(SysPermission::getSort);
        List<SysPermission> allChildren = list(childrenQuery);

        // 将子节点按父ID分组，便于快速查找每个节点的子节点
        Map<Long, List<SysPermission>> childrenMap = allChildren.stream()
                .collect(Collectors.groupingBy(p -> p.getParentId() == null ? 0L : p.getParentId()));

        // 为每个节点设置子节点
        for (SysPermission record : records) {
            List<SysPermission> children = childrenMap.getOrDefault(record.getId(), Collections.emptyList());
            record.setChildren(children);

            // 如果存在子节点，递归处理子节点的树形结构
            if (!children.isEmpty()) {
                tree(children);
            }
        }
    }

    /**
     * 构建权限树
     * 该方法会将权限列表转换为前端所需的树形结构
     * 使用Spring Cache注解实现缓存，提高查询性能
     *
     * @param permissions 权限列表
     * @return 树形结构的权限列表
     */
    @Override
    @Cacheable(value = "permissionTree", key = "'all'", unless = "#result.isEmpty()")
    public List<PermissionTree> permissionTree(List<SysPermission> permissions) {
        // 参数校验
        if (CollectionUtils.isEmpty(permissions)) {
            return Collections.emptyList();
        }

        // 预设集合大小，避免动态扩容
        Map<Long, PermissionTree> nodeMap = new HashMap<>(permissions.size());
        List<PermissionTree> rootNodes = new ArrayList<>();

        // 第一次遍历：创建所有树节点并建立映射关系
        for (SysPermission permission : permissions) {
            PermissionTree node = convertToTreeNode(permission);
            nodeMap.put(permission.getId(), node);
        }

        // 第二次遍历：构建树形结构
        for (SysPermission permission : permissions) {
            PermissionTree currentNode = nodeMap.get(permission.getId());
            if (isRootNode(permission)) {
                rootNodes.add(currentNode);
            } else {
                PermissionTree parentNode = nodeMap.get(permission.getParentId().longValue());
                if (parentNode != null) {
                    parentNode.getChildren().add(currentNode);
                }
            }
        }

        // 对整个树形结构进行排序
        sortTreeNodes(rootNodes);
        return rootNodes;
    }

    @Override
    public List<Long> getPermissionByRoleId(Long roleId) {
        return baseMapper.getPermissionByRoleId(roleId);
    }

    @Override
    public boolean assignPermission(RoleAuthority roleAuthority) {
        if (roleAuthority.isCheck()) {
            return baseMapper.assignPermission(roleAuthority);
        } else {
            return baseMapper.cancelPermission(roleAuthority);
        }
    }

    /**
     * 保存权限信息
     * 保存后清除权限树缓存
     */
    @Override
    @Transactional
    @CacheEvict(value = "permissionTree", allEntries = true)
    public boolean save(SysPermission entity) {
        return super.save(entity);
    }

    /**
     * 更新权限信息
     * 更新后清除权限树缓存
     */
    @Override
    @Transactional
    @CacheEvict(value = "permissionTree", allEntries = true)
    public boolean updateById(SysPermission entity) {
        return super.updateById(entity);
    }

    /**
     * 删除权限信息
     * 删除后清除权限树缓存
     */
    @Override
    @Transactional
    @CacheEvict(value = "permissionTree", allEntries = true)
    public boolean removeById(Serializable id) {
        return super.removeById(id);
    }

    /**
     * 将权限实体转换为树节点
     *
     * @param permission 权限实体
     * @return 树节点
     */
    private PermissionTree convertToTreeNode(SysPermission permission) {
        PermissionTree node = new PermissionTree();
        node.setValue(permission.getId());
        node.setLabel(permission.getName());
        node.setIcon(permission.getIcon());
        node.setChildren(new ArrayList<>());
        return node;
    }

    /**
     * 判断是否为根节点
     * 根节点的判断标准：parentId为null或者为0
     *
     * @param permission 权限实体
     * @return 是否为根节点
     */
    private boolean isRootNode(SysPermission permission) {
        return permission.getParentId() == null || permission.getParentId() == 0;
    }

    /**
     * 对树节点进行排序
     * 递归对每一层级的节点按value进行排序
     *
     * @param nodes 需要排序的节点列表
     */
    private void sortTreeNodes(List<PermissionTree> nodes) {
        if (CollectionUtils.isEmpty(nodes)) {
            return;
        }

        // 对当前层级的节点进行排序
        nodes.sort(Comparator.comparing(PermissionTree::getValue));

        // 递归对子节点进行排序
        for (PermissionTree node : nodes) {
            if (!CollectionUtils.isEmpty(node.getChildren())) {
                sortTreeNodes(node.getChildren());
            }
        }
    }
}